package com.tangding.task;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.tangding.cache.GamesConfigCache;
import com.tangding.cache.GamesDataWatchingCache;
import com.tangding.cache.UserWatchingCache;
import com.tangding.common.exception.GException;
import com.tangding.common.logx.LogHelp;
import com.tangding.common.utils.JacksonUtil;
import com.tangding.hprose.api.client.HproseAsClient;
import com.tangding.net.pool.BaseNettySessionPool;
import com.tangding.service.dao.games.config.GamesConfigRepository;

import io.netty.channel.Channel;

/**
 * @description 
 *
 * @author Ranger
 * @version 2017年12月15日_上午11:49:47
 *
 */
@Component
public class MoonTask {
	
	@Autowired
	BaseNettySessionPool pool;
	@Autowired
	GamesConfigRepository gamesConfigRepository;
	protected ExecutorService poolExe = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() * 2);
	
	@Scheduled(fixedRate=60 * 1000, initialDelay=10)
	public void gamesConfigTask() {
		poolExe.submit(new Runnable() {
			public void run() {
				try {
					Set<String> gamesName = gamesConfigRepository.getGamesName();
					for (String gameName : gamesName) {
						try {
							Object result = HproseAsClient.invoke("QueryGameSettings", gameName);
							GamesConfigCache.configs.put(gameName, result);
						} catch (GException e) {
							LogHelp.doLogAppErr(e);
						}
					}
				} catch (Exception e) {
					LogHelp.doLogException(e);
				}
			}
		});
	}
	
	@Scheduled(fixedRate=5000)
	public void userQueryTask(){
		Set<Object> needQueryIds = UserWatchingCache.getSetsAll();
		if (needQueryIds == null || needQueryIds.size() == 0) {
			return;
		}
		Map<Object, Object> us = new HashMap<>();
		Map<String, Object> request = new HashMap<>();
		request.put("uids", needQueryIds);
		request.put("onlineCondition", 0B11);
		request.put("typeCondition", 0B111);
		poolExe.submit(new Runnable() {
			public void run() {
				try {
					Object result = HproseAsClient.invoke("QueryUsers", request);
					if (result != null) {
						List<Map<String, Object>> users = JacksonUtil.readValue(JacksonUtil.toJson(result), List.class);
						for (Object id : needQueryIds) {
							for (Map<String, Object> product : users) {
								if (!product.containsKey("uid")) {
									continue;
								}
								if (id.toString().equals(product.get("uid").toString())) {
									us.put(id, product);
								}
							}
						};
						
						Enumeration<String> keys = UserWatchingCache.getKeys();
						while (keys.hasMoreElements()) {
							String uid = (String) keys.nextElement();
							Channel channel = pool.getChannel(uid);
							if (channel != null) {
								Set<Object> set = UserWatchingCache.getSet(uid);
								List<Object> list = new ArrayList<>();
								set.forEach(id -> {
									if (us.containsKey(id)) {
										list.add(us.get(id));
									}
								});
								pool.doResponse(uid, "NotifyUsers", list);
							}
						}
					}
				} catch (GException e) {
					LogHelp.doLogAppErr(e);
				}
			}
		});
	}

	@Scheduled(fixedRate=30000)
	public void queryGamesDataTask() {//30秒一次
		poolExe.submit(new Runnable() {
			public void run() {
				try {
					Object result = HproseAsClient.invoke("QueryGamesData");
					if (result == null) {
						return;
					}
					if (GamesDataWatchingCache.watchingSize() > 0) {
						Set<String> uids = GamesDataWatchingCache.getSet();
						uids.forEach(uid -> {
							pool.doResponse(uid, "UpdateGamesData", result);
						});
					}
					
					Map<String, Object> data = (Map<String, Object>) result;
					if (data != null) {
						Long maxLimit = (Long) data.get("maxLimit");
						Long waterLevel = (Long) data.get("waterLevel");
						if (maxLimit != null && waterLevel != null && waterLevel.longValue() > maxLimit.longValue()) {//超过最大限制
							Collection<String> onlines = pool.onlines();
							if (onlines != null && onlines.size() > 0) {//给所有在线管理员发送
								for (String uid : onlines) {
									pool.doResponse(uid, "GameServerInfo", "平台输赢已经触碰到天花板，所有管控操作失效！");
								}
							}
						}
					}
				} catch (GException e) {
					LogHelp.doLogAppErr(e);
				}
			}
		});
		
		
		/*if (GamesDataWatchingCache.watchingSize() > 0) {
			poolExe.submit(new Runnable() {
				public void run() {
					try {
						Object result = HproseAsClient.invoke("QueryGamesData");
						Set<String> uids = GamesDataWatchingCache.getSet();
						uids.forEach(uid -> {
							pool.doResponse(uid, "UpdateGamesData", result);
						});
						
						Map<String, Object> data = (Map<String, Object>) result;
						if (data != null) {
							Long maxLimit = (Long) data.get("maxLimit");
							Long waterLevel = (Long) data.get("waterLevel");
							if (maxLimit != null && waterLevel != null && waterLevel.longValue() > maxLimit.longValue()) {//超过最大限制
								Collection<String> onlines = pool.onlines();
								if (onlines != null && onlines.size() > 0) {//给所有在线管理员发送
									for (String uid : onlines) {
										pool.doResponse(uid, "GameServerInfo", "平台输赢已经触碰到天花板，所有管控操作失效！");
									}
								}
							}
						}
					} catch (GException e) {
						LogHelp.doLogAppErr(e);
					}
				}
			});
		}*/
	}
}
